home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Development Tools & Languages / Macintosh Common Lisp Related / User Contributions / zebu v3.3.3 (LALR parser) / zebu-loader.lisp < prev    next >
Encoding:
Text File  |  1994-09-12  |  18.4 KB  |  487 lines  |  [TEXT/ttxt]

  1. ; -*- mode:     CL -*- ----------------------------------------------------- ;
  2. ; File:         zebu-loader.l
  3. ; Description:  load a ZEBU grammar table
  4. ; Author:       Joachim H. Laubsch
  5. ; Created:       6-Nov-90
  6. ; Modified:     Thu May 12 10:57:29 1994 (Joachim H. Laubsch)
  7. ; Language:     CL
  8. ; Package:      ZEBU
  9. ; Status:       Experimental (Do Not Distribute) 
  10. ; RCS $Header: $
  11. ;
  12. ; (c) Copyright 1990, Hewlett-Packard Company
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14. ; Revisions:
  15. ; RCS $Log: $
  16. ; 13-Jan-93 (Joachim H. Laubsch)
  17. ;  implemented terminal-alist access via the vector terminal-alist-SEQ
  18. ;  5-Nov-91 (Joachim H. Laubsch)
  19. ;  removed dependency on LUCID in the use of backquoted expressions
  20. ;  in semantic actions
  21. ; 16-Jul-91 (Joachim H. Laubsch)
  22. ;  Added a facility to deal with multiple grammars
  23. ;  lr-parse takes a third argument, a grammar
  24. ;  READ-PARSER and LIST-PARSER take a :grammar keyword argument, defaulting to
  25. ;  *current-grammar*
  26. ;  in order to use several grammars we need several 
  27. ;    *IDENTIFIER-CONTINUE-CHARS*, *IDENTIFIER-START-CHARS*
  28. ;    
  29. ;  1-Mar-91 (Joachim H. Laubsch)
  30. ;  did monitoring, found that 75% of the time is in the lexer.
  31. ;  rewrote ZEBU::RECOGNIZE-TOKEN to use a hashtable of terminal-tokens
  32. ;  this sped up this function by a factor of 35. Speed-up of READ-PARSER: 3.5
  33. ; 11-Dec-90 (Joachim H. Laubsch)
  34. ;  Introduce the ZEBU package
  35. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  36. (in-package "ZEBU")
  37. (provide "zebu-loader")
  38.  
  39. ;;; The following data structures are loaded from a parse table file by the 
  40. ;;; function which follows.
  41. ;;;
  42. ;;; lexicon is a vector of strings or lisp symbols , indexed by the 
  43. ;;; "grammar symbol indices",  which are the instantiations of
  44. ;;; the grammar symbols.
  45. ;;;
  46. ;;; terminal-indices is a list of the grammar symbol indices indicating
  47. ;;; which among them are terminal symbols.
  48. ;;;
  49. ;;; production-info is a vector, indexed by the production indices.
  50. ;;; Each item is a cons: the cars index the symbols
  51. ;;; which are the lhs of the productions, the cdrs indicate the
  52. ;;; lengths of the productions.
  53. ;;;
  54. ;;; action-table is a vector indexed by the state indices.
  55. ;;; Each state's entry is a vector whose elements represent
  56. ;;; defined entries in the action parsing function. These entries are 3 element
  57. ;;; lists whose first elements are the indices of the grammar symbol argument
  58. ;;; to the action parsing function.  The second elements in the lists are an
  59. ;;; encoding of the action function: 's for shift, 'r for reduce, 'a for
  60. ;;; accept.  The third elements are production or next state indices as
  61. ;;; approprite.  The three element lists appear in their surrounding
  62. ;;; vectors sorted on their cars.
  63. ;;;
  64. ;;; goto-table is arranged similar to action-table but has two element
  65. ;;; lists instead of three.  The second element of each list are the
  66. ;;; index of the state to goto.
  67. ;;; 
  68. ;;; end-symbol-index holds the index of the end symbol.
  69. ;;;
  70. ;;; terminal-alist associates terminal symbol instantiations with
  71. ;;; their indices.
  72. ;;;
  73. ;;; client-lambdas are a vector of procedures, indexed by production index,
  74. ;;; which correspond to productions in the grammar.  The client lambdas are 
  75. ;;; what the parser calls to do syntax directed something by side effect.
  76.  
  77. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  78. ;;                             Zebu Grammar Struct
  79. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  80. ;; helps define the function that computes whether a character can continue 
  81. ;; a symbol
  82.  
  83. (defvar *identifier-continue-chars*
  84.   "$-_*.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890?"
  85.   "Characters that may occur in an identifier. Set this before calling zebu-load-file.")
  86.  
  87. (defvar *identifier-start-chars* "$-*?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  88.   "Characters that may start an identifier.")
  89.  
  90. ;----------------------------------------------------------------------------;
  91. ; *string-delimiter*, *symbol-delimiter*
  92. ;---------------------------------------
  93. ;; An NLL-constant can now be a string or a symbol. A string is surrounded
  94. ;; by double-quotes (#\"), as in: P(arg1: \"|Jon Doe's Deli|\")
  95. ;; A symbol is surrounded by single-quotes (#\'), as in: 
  96. ;;     P(arg1: 'Jon Doe')
  97. ;; or  P(arg1: '|Jon Doe|')
  98. ;; By default, the single-quotes may be omitted at parsing in case the
  99. ;; symbol contains only characters which are in
  100. ;;    (grammar-identifier-continue-chars *current-grammar*)
  101. ;; as in P(arg1: Jon_Doe)
  102. ;; Either set these variables before the grammar is loaded
  103. ;;   or   supply the initial values explicitely in the .grm file
  104. ;;        e.g. (:name "nll" :string-delimiter #\" :symbol-delimiter #\')
  105. (defvar *string-delimiter* #\"
  106.   "Delimits a lexical token, considered as a STRING.")
  107.  
  108. (defvar *symbol-delimiter* #\'
  109.   "Delimits a lexical token, considered as a SYMBOL.")
  110.  
  111. (defvar *preserve-case* nil
  112.   "If true, the case of an identifier will be preserved (default false).")
  113.  
  114. (defvar *case-sensitive* nil
  115.   "If true, the case of a keyword matters otherwise case is ignored when \
  116. looking for the next token (default false).")
  117.  
  118. (defvar *disallow-packages* nil
  119.   "If false, Zebu parses identifiers as symbols possibly qualified by a package")
  120.     
  121. ;----------------------------------------------------------------------------;
  122. ; grammar
  123. ;--------
  124. (defstruct (grammar (:print-function print-grammar))
  125.   name
  126.   lexicon
  127.   terminal-indices
  128.   production-info
  129.   action-table
  130.   goto-table
  131.   lr-parser-start-state-index
  132.   end-symbol-index
  133.   client-lambdas
  134.   identifier-index
  135.   string-index
  136.   (number-index nil)
  137.   (identifier-continue-chars     *identifier-continue-chars* :type string)
  138.   (identifier-continue-chars-V   (make-array char-code-limit :element-type 'bit
  139.                          :initial-element 0))
  140.   (identifier-start-chars        *identifier-start-chars* :type string)
  141.   (identifier-start-chars-V      (make-array char-code-limit :element-type 'bit
  142.                          :initial-element 0))
  143.   ;; a vector to be indexed by the char-code of the first character of a key
  144.   ;; each element contains an alist of pairs: (,terminal-token . ,index)
  145.   (terminal-alist-SEQ            (make-sequence 'vector
  146.                         char-code-limit
  147.                         :initial-element nil))
  148.   (case-sensitive                *case-sensitive*)
  149.   (string-delimiter              *string-delimiter* :type character)
  150.   (symbol-delimiter              *symbol-delimiter* :type character)
  151.   file
  152.   (package                       *package*)
  153.   grammar                ; the grammar used to parse the
  154.                     ; grammar being defined
  155.                     ; defaults to the null-grammar
  156.                     ; but you can use the meta-grammar
  157.   (zb-rules ())
  158.   (domain ())
  159.   domain-file
  160.   (lex-cats ())                ; an alist of cateory name and
  161.                     ; regular expressions
  162.   (lex-cat-map ())            ; an alist of index and reg-ex function
  163.   (white-space                  '(#\Space #\Newline #\Tab))
  164.   (intern-identifier            t)    ; Identifier is represented as symbol
  165.   (id-allows-start-digit        nil)    ; An Identifier may start with a digit
  166.   )
  167.  
  168. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  169. ;;                                Null Grammar
  170. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  171. (defvar *NULL-Grammar* (make-grammar :name "null-grammar"))
  172.  
  173. (defun print-grammar (item stream level)
  174.   (declare (ignore level))
  175.   (format stream "<Zebu Grammar: ~A>" (grammar-name item)))
  176.  
  177. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  178. ;;                             register a grammar
  179. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  180. (defvar *all-grammars*
  181.   (list (cons (grammar-name *NULL-Grammar*) *NULL-Grammar*)))
  182.  
  183. (defun find-grammar (name)
  184.   (cdr (assoc (string name) *all-grammars* :test #'equal)))
  185.  
  186. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  187. ;;                            Lexical Analysis Info
  188. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  189. (defvar *identifier-continue-chars-V*)
  190. (declaim (inline identifier-continue-char-p))
  191. (defun identifier-continue-char-p (char)
  192.   (declare (character char))
  193.   (= 1 (sbit *identifier-continue-chars-V* (char-code char))))
  194.  
  195. (defvar *identifier-start-chars-V*)
  196. (declaim (inline identifier-start-char-p))
  197. (defun identifier-start-char-p (char)
  198.   (declare (character char))
  199.   (= 1 (sbit *identifier-start-chars-V* (char-code char))))
  200.  
  201. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  202. ;;                                   Lex-Cats
  203. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  204.  
  205. (declaim (inline add-to-lex-cat-map))
  206. ;; preserve the order of the definition
  207.  
  208. (defun add-to-lex-cat-map (index terminal-token grammar)
  209.   (setf (grammar-lex-cat-map grammar)
  210.     (nconc (grammar-lex-cat-map grammar)
  211.            (list (cons index (symbol-function terminal-token))))))
  212.  
  213. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  214. ;;                               Debugging 
  215. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  216.  
  217. (defvar *grammar-debug* nil
  218.   "If TRUE at compile or load time, the parser emits traces, else not.")
  219.  
  220. (defmacro if-debugging (&rest x)
  221.   `(progn . ,(if *grammar-debug*
  222.          x
  223.            'nil)))
  224.  
  225. (eval-when (compile)
  226.   (setq *grammar-debug* nil))
  227.  
  228. #||
  229. (eval-when (eval)
  230.   (setq *grammar-debug* T))
  231. ||#
  232.  
  233. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  234. ;;         Read in a set of parse tables as written by (dump-tables) .
  235. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  236.  
  237. (defun zebu-load-file (filename &key (verbose t)
  238.                &aux lexicon terminal-indices (*package* *package*))
  239.   ;; returns a grammar and registers this grammar on *all-grammars*
  240.   (let ((path (probe-file (merge-pathnames
  241.                filename
  242.                (merge-pathnames (make-pathname :type "tab")))))
  243.     (*load-verbose* verbose))
  244.     (if path
  245.     (when verbose
  246.       (format t "~%Loading ~s" (namestring path)))
  247.       (error "File not found: ~S" filename))
  248.     (unless (equal (pathname-type path) "tab")
  249.       (let ((name (pathname-name path)))
  250.     (cerror "~S is now compiled."
  251.         "~S is not a Zebu output!~%;;; Compile ~S first!"
  252.         name filename name)
  253.     (setf path (merge-pathnames (make-pathname :type "tab") path)
  254.           filename (namestring path))))
  255.     (with-open-file (port filename :direction :input)
  256.       (let ((options            ; 1: read grammar-options
  257.          (catch 'read-grammar-options
  258.            (check-grammar-options (read port) filename nil))))
  259.     (unless options
  260.       (close port)
  261.       (setq port (open filename :direction :input))
  262.       (setq options
  263.         (catch 'read-grammar-options
  264.           (check-grammar-options (read port) filename nil))))
  265.     (let* ((g (apply #'make-grammar options))
  266.            (terminal-alist-SEQ (grammar-terminal-alist-SEQ g)))
  267.       (declare (type grammar g))
  268.       (prepare-domain (grammar-domain g))
  269.       ;; 1a: load the domain file
  270.       (let ((grammar-domain-file (grammar-domain-file g)))
  271.         (when grammar-domain-file
  272.           (let ((grammar-domain-file-name
  273.              (pathname-name (pathname grammar-domain-file))))
  274.         (or (block find-domain-file
  275.               (dolist (type (append *load-binary-pathname-types*
  276.                         *load-source-pathname-types*))
  277.             (dolist (domain-path (list path (grammar-file g)))
  278.               (let ((domain-file 
  279.                  (merge-pathnames
  280.                   (make-pathname 
  281.                    :name grammar-domain-file-name
  282.                    :type type)
  283.                   domain-path)))
  284.                 (when (probe-file domain-file)
  285.                   (when *load-verbose*
  286.                 (format t "~%Loading domain file ~s"
  287.                     (namestring domain-file)))
  288.                   (return-from find-domain-file
  289.                 (load domain-file)))))))
  290.             (warn "No domain file found")))))
  291.  
  292.       ;; 2: read grammar-lexicon
  293.       (setf (grammar-lexicon g)          (setf lexicon (read port))
  294.         ;; 3: read grammar-terminal-indices
  295.         (grammar-terminal-indices g) (setf terminal-indices (read port))
  296.         ;; 4: read grammar-production-info
  297.         (grammar-production-info g)  (read port))
  298.       (let ((old-grammar (assoc (grammar-name g) *all-grammars*
  299.                     :test #'string=)))
  300.         (if old-grammar
  301.         (setf (cdr old-grammar) g)
  302.           (setf *all-grammars* (acons (grammar-name g) g *all-grammars*))))
  303.     
  304.       ;; 5: read grammar-action-table
  305.       (let ((*package* *ZEBU-PACKAGE*))
  306.         (setf (grammar-action-table g) 
  307.           (vectorize-vector-of-lists (read port))))
  308.     
  309.       ;; 6: read grammar-goto-table
  310.       (setf (grammar-goto-table g) (vectorize-vector-of-lists (read port))
  311.         ;; 7: read grammar-lr-parser-start-state-index
  312.         (grammar-lr-parser-start-state-index g) (read port)
  313.         ;; 8: read grammar-end-symbol-index
  314.         (grammar-end-symbol-index g) (read port)
  315.         ;; 9: read grammar-client-lambdas
  316.         (grammar-client-lambdas g) (read-parser-actions port g))
  317.  
  318.       ;; IDENTIFIER-START-CHARS"
  319.       (let ((identifier-start-chars-V
  320.          (grammar-identifier-start-chars-V g))
  321.         (identifier-start-chars (grammar-identifier-start-chars g)))
  322.         (dotimes (i (length identifier-start-chars))
  323.           (let ((c (schar identifier-start-chars i)))
  324.         (declare (character c))
  325.         (setf (sbit identifier-start-chars-V (char-code c))
  326.               1)
  327.         (when (digit-char-p c)
  328.           (setf (grammar-id-allows-start-digit g) t)))))
  329.  
  330.       ;; IDENTIFIER-CONTINUE-CHARS"
  331.       (let ((identifier-continue-chars-V
  332.          (grammar-identifier-continue-chars-V g))
  333.         (identifier-continue-chars
  334.          (grammar-identifier-continue-chars g)))
  335.         (dotimes (i (length identifier-continue-chars))
  336.           (setf (sbit identifier-continue-chars-V
  337.               (char-code
  338.                (the character
  339.                 (schar identifier-continue-chars i))))
  340.             1)))
  341.  
  342.       ;; sort the terminal-alist so that terminals with the same
  343.       ;; initial string are sorted by decreasing length
  344.       ;; i.e. if "?" and "?u?" are both terminals, then "?u?"
  345.       ;; should be found first.
  346.       ;; This can simply be achieved by sorting according to 
  347.       ;; ascending key length.
  348.       (dotimes (i (length (the simple-vector terminal-indices)))
  349.         (let* ((index (svref terminal-indices i))
  350.            (terminal-token (svref lexicon index)))
  351.           (declare (string terminal-token))
  352.           (typecase terminal-token
  353.         (string
  354.          (let ((char1-code
  355.             (char-code (let ((c (schar terminal-token 0)))
  356.                     (declare (character c))
  357.                     (if (grammar-case-sensitive g)
  358.                     c
  359.                       (char-downcase c)))))
  360.                (token-association `(,terminal-token . ,index)))
  361.            ;; keep a table indexed by char-code of first-char
  362.            ;; of the terminal tokens
  363.            (let ((bucket (elt terminal-alist-SEQ char1-code)))
  364.              (setf (elt terminal-alist-SEQ char1-code)
  365.                (if bucket
  366.                    (sort (cons token-association bucket)
  367.                      #'(lambda (a b) (declare (string a b))
  368.                            (> (length a) (length b)))
  369.                      :key #'car)
  370.                  (list token-association))))))
  371.         (symbol
  372.          (let ((terminal-token-name (symbol-name terminal-token)))
  373.            (declare (string terminal-token-name))
  374.            (cond ((string= terminal-token-name "IDENTIFIER")
  375.               (setf (grammar-identifier-index g) index))
  376.              ((string= terminal-token-name "STRING")
  377.               (setf (grammar-string-index g) index))
  378.              ((string= terminal-token-name "NUMBER")
  379.               (setf (grammar-number-index g) index))
  380.              ;; for lexical categories: remember index
  381.              ((assoc terminal-token (grammar-lex-cats g))
  382.               (add-to-lex-cat-map index terminal-token g))
  383.              (t (warn "If ~S is a terminal it should be a string, not a symbol.~%If it's a non-terminal it's undefined."
  384.                   terminal-token))))))))
  385.       g)))))
  386.  
  387. (defun read-parser-actions (port grammar)
  388.   ;; zb-rules = [(<NT> . <zb-rule>) ...]
  389.   (let ((zb-rules (read port))
  390.     (actions  (make-sequence
  391.            'vector
  392.            (length (grammar-production-info grammar))))
  393.     (actions-idx 1))
  394.     (setf (svref actions 0) :PLACE-HOLDER)
  395.     (dotimes (i (length zb-rules))
  396.       (let ((pair (svref zb-rules i)))
  397.     (let ((zb-rule (cdr pair)))
  398.       (dolist (prod (zb-rule--productions zb-rule))
  399.         (let ((action (production-rhs--build-fn prod)))
  400.           (setf (svref actions actions-idx)
  401.             (if (symbolp action)
  402.             (if (or (eq action 'identity) (null action))
  403.                 nil
  404.               (if (fboundp action)
  405.                   (symbol-function action)
  406.                 (progn
  407.                   (warn "At parse time, ~S should be defined."
  408.                     action)
  409.                   action)))
  410.               action
  411.               ;; (if (fboundp 'compile)
  412.               ;;    (compile nil action)
  413.               ;;   (eval `(function ,action)))
  414.               ))
  415.           (incf actions-idx))))))
  416.     (setf (grammar-zb-rules grammar) zb-rules)
  417.     actions))
  418.  
  419. (defun vectorize-vector-of-lists (V  &aux alist)
  420.   (declare (simple-vector V) (dynamic-extent alist))
  421.   (dotimes (i (length V) V) 
  422.     (let* ((sublist (svref V i))
  423.        (pair (assoc sublist alist :test #'equal)))
  424.       (if pair
  425.       (setf (svref v i) (cdr pair))
  426.     (let ((subV (list->vector sublist)))
  427.       (setf (svref v i) subV)
  428.       (push (cons sublist subV) alist))))))
  429.  
  430.  
  431. ;----------------------------------------------------------------------------;
  432. ; load-from-command-line (for UNIX)
  433. ;----------------------------------
  434. ; Load a compiled grammar from a command line argument:
  435. ;    Zebu-Parser ex1.tab
  436. ; Zebu-Parser <comiled-grammar> -l <file to load before grammar>
  437. ;             -e "<form to be evaluated>"
  438. ;             -quit 
  439. #+LUCID
  440. (defun load-from-command-line ()
  441.   (let ((*default-pathname-defaults*
  442.      (make-pathname :directory
  443.             (pathname-directory (working-directory))))
  444.     (help "Zebu-Parser [-zb] <compiled-grammar> [-l <file>]*
  445.   [-e <form to eval>]*  [-quit]"))
  446.     (handler-case
  447.      (do* ((i 1 (1+ i))
  448.        (arg (command-line-argument i) (command-line-argument i))
  449.        (val (command-line-argument (1+ i))
  450.         (command-line-argument (1+ i))))
  451.       ((null arg)
  452.        (when (= i 1)
  453.          (progn (warn "~a" help) (quit))))
  454.        ;;(format t "~%arg: ~s val: ~s" arg val)
  455.        (cond ((equal arg "-l")
  456.           (incf i) (load val))
  457.          ((equal arg "-e")
  458.           (incf i) (eval (read-from-string val)))
  459.          ((equal arg "-quit") (quit))
  460.          ((equal arg "-h")
  461.           (format t "~%~a" help))
  462.          ((equal arg "-zb")
  463.           (incf i) (zebu-load-file val :verbose t))
  464.          (t (if (probe-file arg)
  465.             (zebu-load-file arg :verbose t)
  466.           (progn
  467.             (warn "Unrecognized argument ~S~%~a" arg help)
  468.             (quit))))))
  469.      (error (c)
  470.         (format t "~&Zebu-Parser failed: ~A~%" c)
  471.         (quit)))))
  472.  
  473. ;----------------------------------------------------------------------------;
  474. ; zebu-load-top
  475. ;--------------
  476. ; interactive loader invocation
  477. (defun zebu-load-top ()
  478.   (format t "~&Enter the name of a Zebu .tab file to load: ")
  479.   (let ((ifile (read-line t)))
  480.     (zebu-load-file ifile)))
  481.  
  482. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  483. ;;                            End of zebu-loader.l
  484. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  485.